#pragma once
#include <bondlib/RealTimeDeal/IRealTimeDealModel.h>
#include <bondlib/BondContainer.h>
#include <vector>
#include <map>

namespace detail{
	struct ColumnOrder{
		int		comlumn;				// 不是实际的列编号,必须是VSortKey
		bool	ascend;					// true:递增排序,false:递减排序
	};

	typedef int(*FieldComparator)(const void* f1, const void* f2);
	struct FieldInfo{
		int				sort_type;		// 排序类型,取值为kSortType
		int				column_id;		// 列编号,VSortKey,实际上是列对应的全局排序key
		int				field_bytes;	// 该列字段占用字节数
		FieldComparator	comparator;		// 该字段的比较器
		const char*		column_name;	// 用于调试用,保存列名称
	};
	struct SortInfo{
		int				sort_type;		// 排序类型,列排序产生的数据如何比较
		int				column_id;		// 列编号,该列的排序用的数据如何产生
		int				field_bytes;	// 该列排序产生的数据占用字节数
		FieldComparator	comparator;		// 该字段的比较器,通用比较器只比较递增
		int				offset;			// 该字段在该记录中的偏移位置
		bool			ascend;			// 递增排序,递减排序
	};
	struct IssuePeriod{
		int		nBondIndex;
		int		nAscend;
		int		nDate;
	};
#define GetBond(i) CBondContainer::instance().ElementAtR(i)
#define GetDoubleFlag(d) (d) > 0.000001 ? 1 : ((d) < -0.000001 ? (-1) : 0)

	class IBondReader{
	public:
		virtual ~IBondReader(){}
		virtual bool GetRecordField(const void* key, int col, char* field, int capcity)=0;
		virtual void PreGetRecordField(const std::vector<SortInfo>& orders, int corpid)=0;
	};

	class SortKeyManager{
		typedef std::map<int, FieldInfo> FiledInfoMap;
		// 存放着所有SortKey的字段信息,全局的,可以共享
		// bond的每列信息,创建后基本不变
		FiledInfoMap					m_fields;
	public:
		static SortKeyManager& Get();
		SortKeyManager();
		~SortKeyManager();
		void SetFieldImpl(int column, const char* name, int sortType, int bytes);
		bool GetFieldInfo(int column, FieldInfo& fi);
	};
	/*
	此对象可能会消耗
	债券个数*经纪商个数*(排序列字段总字节+sizeof(BrokerKeyInfo))
	债券个数*经纪商个数*(sizeof(INDEX))

	当有5w债券,5个经纪商,那么最大消耗内存大概是
	发行人机构全称	25w*(8+8+128)	= 34mb
	代码					25w*(8+8+12)	= 7mb
	简称					25w*(8+8+32)	= 12mb
	*/
	class CSortBuffer{
		typedef DealIndex KeyType;
		typedef std::map<int, FieldInfo> FiledInfoMap;
		typedef std::map<int, FieldComparator> ComparatorMap;
		// 一条记录的头部大小,是KeyType的大小
		// 排序大量数据的时候,会将KeyType值和要排序的字段组合成
		// 一条待排序的记录,所有待排序的记录紧密相联,作为固定大小的数组,存放在m_buffer中
		// 其中INDEX.index表示数组的索引,offset表示index*排序记录的大小
		// m_buffer+INDEX.offset即每条待排序的记录
		// 在每条待排序记录中,SortInfo.offset表示每个待排序字段的偏移量
		struct INDEX{
			int		index;
			int		offset;
			INDEX(int i, int o) :index(i), offset(o){}
		};
		int								m_comp_count;		// 记录std::sort中的比较次数,用于调试
		std::vector<SortInfo>			m_sortinfos;		// 比较信息
		char*							m_buffer;			// 全排后的所有排序记录的内存
		int								m_capcity;			// m_buffer 的实际内存大小
		

		// 存放着每种排序类型对应的比较函数指针,全局可以共享
		// 持有的排序类型的比较函数的表
		ComparatorMap					m_comparators;		

		// 准备排序的INDEX数组
		// 排序前,为0-总个数分别指向m_buffer中的排序记录的索引
		std::vector<INDEX>				m_indexes;			
	public:
		CSortBuffer();
		~CSortBuffer();
		char* PrepareBuffer(int nCount, int nRecordSize);
		void SetComparator(int type, FieldComparator comparator);
		int CompareRecord(const INDEX& k1, const INDEX& k2);
		void CheckSort();
		FieldComparator GetComparator(int type);


		void Sort(std::vector<KeyType>& keys, const std::vector<SortInfo>& sortinfos, int ncorpid, int recordSize, IBondReader* reader);

	protected:
		void LoadSortData(std::vector<KeyType>& keys, std::vector<SortInfo>& sortinfos, int recordSize, IBondReader*	reader);

	};
}
